package com.morty.openapi;

import com.alibaba.fastjson.JSON;
import com.morty.pojo.Result;
import lombok.extern.log4j.Log4j2;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;

@Component
@Log4j2
public class OpenApiGatewayFilterFactory implements GatewayFilterFactory<OpenApiGatewayFilterFactory.Config>, Ordered {

    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
    private static final String WWW_AUTHENTICATE_FORMAT = "Basic realm=\"Realm\"";
    private static final String AUTHENTICATION_SCHEME_BASIC = "Basic";

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            log.debug("open-api-OpenApiFilter start");
            ServerHttpRequest request;
            try {
                //TODO 用户登录校验
                Result<Object> checkR = new Result();
                if (checkR.getCode() != 200) {
                    log.error("auth接口校验失败：{},errorMsg:{}",
                            JSON.toJSONString(""),
                            checkR.getMessage());
                    return error(exchange, checkR.getMessage());
                }
                //TODO addHeaders
                request = exchange.getRequest().mutate().build();
            } catch (Exception e) {
                log.error("用户校验异常:", e);
                return error(exchange, e.getMessage());
            }
            return chain.filter(exchange.mutate().request(request).build());
        });
    }

    private Mono<Void> error(ServerWebExchange exchange) {
        return error(exchange, "");
    }

    private Mono<Void> error(ServerWebExchange exchange, String errorMsg) {
        ServerHttpResponse resp = exchange.getResponse();
        resp.setStatusCode(HttpStatus.UNAUTHORIZED);
        resp.getHeaders().set(WWW_AUTHENTICATE, WWW_AUTHENTICATE_FORMAT);
        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        Result<String> returnData = new Result<>(HttpStatus.UNAUTHORIZED.value(), errorMsg);
        String returnStr = JSON.toJSONString(returnData);
        DataBuffer buffer = resp.bufferFactory().wrap(returnStr.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Mono.just(buffer));
    }

    @Override
    public Class<Config> getConfigClass() {
        return Config.class;
    }

    @Override
    public Config newConfig() {
        return new Config();
    }

    @Override
    public int getOrder() {
        return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER - 2;
    }

    public static class Config {

    }
}
